#include "offlinehandler.h"

OfflineHandler *OfflineHandler::instance = nullptr;

OfflineHandler::OfflineHandler() {

}

OfflineHandler *OfflineHandler::getInstance() {
    if (instance == nullptr) {
        instance = new OfflineHandler();
    }
    return instance;
}

void OfflineHandler::startSlot() {
    qDebug() << "\033[35m =] startSlot() \033[0m";
    connect(TRANS, SIGNAL(pingOnline(InfoHead*, QByteArray, QDataStream*, qint8, QHostAddress, quint16)),
            this, SLOT(pingOnline(InfoHead*, QByteArray, QDataStream*, qint8, QHostAddress, quint16)));
    connect(TRANS, SIGNAL(rePingOnline(InfoHead*, QByteArray, QDataStream*, qint8, QHostAddress, quint16)),
            this, SLOT(rePingOnline(InfoHead*, QByteArray, QDataStream*, qint8, QHostAddress, quint16)));
}

void OfflineHandler::pingOnline(InfoHead *infoHead,
                                QByteArray dataBytes,
                                QDataStream *dataStream,
                                qint8 dataType,
                                QHostAddress senderIp,
                                quint16 senderPort) {
    // 筛除不可ping
    if (infoHead->getDes() == 0
            || infoHead->getOperation() == Operation::SendGroupTextMsg) {
        qDebug() << "\033[35m =] this is 不可ping \033[0m";
        if (dataType == 0) {
            TRANS->getOperation()->exec(infoHead, dataBytes, senderIp, senderPort);
        } else if (dataType == 1) {
            ServerOperationThread *operationThread = new ServerOperationThread();
            operationThread->setInfoHead(infoHead);
            operationThread->setDataStream(dataStream);
            operationThread->setIp(senderIp);
            operationThread->setPort(senderPort);
            operationThread->run();
        } else {
            qDebug() << "\033[32mOfflineHandler::pingOnline [if cantPing] into unbelievable block\033[0m";
        }
        return;
    }

    QSqlTableModel *userIpModel;
    userIpModel = new QSqlTableModel();
    userIpModel->setTable("user_ip");
    userIpModel->setFilter(QObject::tr("user_id = %1").arg(infoHead->getDes()));
    userIpModel->select();
    QString reIp = userIpModel->record(0).value("ip").toString();

    keeperList.push_back(
                InfoTimerKeeper{
                    QObject::startTimer(3000),
                    infoHead,
                    dataBytes,
                    dataStream,
                    dataType,
                    senderIp,
                    senderPort
                });

    TRANS->writeUdp(new InfoHead(0,
                                 0,
                                 Operation::PingOnline,
                                 Operation::Success,
                                 keeperList.back().timerId,
                                 infoHead->getDes(),
                                 QString("")),
                    QByteArray(),
                    QHostAddress(reIp),
                    SYSCONF.udpPort);


    qDebug() << "===========testOnline=======\t" << "=> start timer ============";
    qDebug() << "keeperQueue.back().timerId: \t" << keeperList.back().timerId;
    qDebug() << "keeperQueue.back().senderIp: \t" << keeperList.back().senderIp;
    qDebug() << "keeperQueue.back().senderPort: \t" << keeperList.back().senderPort;
    qDebug() << "keeperQueue.back()...getDes(): \t" << keeperList.back().infoHead->getDes();
    qDebug() << "keeperQueue.back()...reIp: \t" << reIp;
    qDebug() << "";
}

void OfflineHandler::timerEvent(QTimerEvent *event) {
    qDebug() << "\033[35m =] < time out ! > \033[0m";
    for (auto it = keeperList.begin(); it != keeperList.end(); ++it) {
        if ((*it).timerId == event->timerId()) {  // 对方不在线，消息离线化
            ServerOperationThread *operationThread = new ServerOperationThread();

            switch (static_cast<Operation::Opcode>((*it).infoHead->getOperation())) {
                case Operation::SendTextMsg:
                    (*it).infoHead->setOperation(Operation::OfflineSendTextMsg);
                    break;
                case Operation::SendImgMsg:
                    (*it).infoHead->setOperation(Operation::OfflineSendImgMsg);
                    break;
                case Operation::SendVoiceMsg:
                    (*it).infoHead->setOperation(Operation::OfflineSendVoiceMsg);
                    break;
                default:
                    qDebug() << "\033[32mOfflineHandler::timerEvent switch in default case \033[0m";
            }
            operationThread->setInfoHead((*it).infoHead);

            QSqlTableModel *userIpModel;
            userIpModel = new QSqlTableModel();
            userIpModel->setTable("user_ip");
            userIpModel->setFilter(QObject::tr("user_id = %1").arg((*it).infoHead->getDes()));
            userIpModel->select();
            QString reIp = userIpModel->record(0).value("ip").toString();
            operationThread->setIp(QHostAddress(reIp));

            if ((*it).dataType == 0) {
                QDataStream in(&(*it).dataBytes, QIODevice::ReadOnly);
                operationThread->setDataStream(&in);
                operationThread->setPort(6666);
            } else if ((*it).dataType == 1) {
                operationThread->setDataStream((*it).dataStream);
                operationThread->setPort(7777);
            } else {
                qDebug() << "\033[32mOfflineHandler::timerEvent [if] into unbelievable block\033[0m";
            }

            operationThread->run();

            keeperList.erase(it);
        }
    }
}

void OfflineHandler::rePingOnline(InfoHead *infoHead,
                                  QByteArray dataBytes,
                                  QDataStream *dataStream,
                                  qint8 dataType,
                                  QHostAddress senderIp,
                                  quint16 senderPort) {
    qDebug() << "\033[35m =] < is online! > \033[0m";
    QObject::killTimer(infoHead->getDes());

    QSqlTableModel *userIpModel;
    userIpModel = new QSqlTableModel();
    userIpModel->setTable("user_ip");
    userIpModel->setFilter(QObject::tr("user_id = %1").arg(infoHead->getDes()));
    userIpModel->select();
    QString reIp = userIpModel->record(0).value("ip").toString();

    for (auto it = keeperList.begin(); it != keeperList.end(); ++it) {
        if ((*it).timerId == infoHead->getDes()) {
            // 对方在线，正常执行
            if ((*it).dataType == 0) {
                TRANS->getOperation()->exec((*it).infoHead, (*it).dataBytes, (*it).senderIp, (*it).senderPort);
            } else if ((*it).dataType == 1) {
                ServerOperationThread *operationThread = new ServerOperationThread();
                operationThread->setInfoHead((*it).infoHead);
                operationThread->setDataStream((*it).dataStream);
                operationThread->setIp(QHostAddress(reIp));
                operationThread->setPort(7777); // 接收者的端口目前是不可知的，暂约定为7777
                operationThread->run();
            } else {
                qDebug() << "\033[32mOfflineHandler::rePingOnline [if] into unbelievable block\033[0m";
            }
            keeperList.erase(it);
        }
    }
}
